<template>
  <div>
    <!-- 模板中不用.value, 因为编译模板中会自动.value -->
    <h2>count: {{count}}</h2>
    <h2>msg: {{msg}}</h2>
    <h2>user: {{user}}</h2>
    <h2>numbers: {{numbers}}</h2>
    
    <button @click="update">更新</button>
  </div>
</template>


<script lang="ts">
  import {
    ref,
    reactive,
    toRefs,
    watch,
  } from 'vue'

  interface IState {
    msg: string
    user: {
      name: string
      age: number
      sex?: string
    },
    numbers: number[]
  }


  export default {
    name: 'About',

    setup () {
      const count = ref(1)


      // 创建一个reactive响应对象
      const state = reactive<IState>({
        msg: 'atguigu',
        user: {
          name: 'tom',
          age: 12
        },
        numbers: [1, 3, 5]
      })
      console.log(state)

      // 监视单个ref数据
      watch(count, (newVal, oldVal) => {
        console.log('watch', newVal, oldVal)
      }, {immediate: true, deep: true})

      // 监视单个reactive数据
      watch(() => state.msg, (value) => {
        console.log('watch2', value)
      })

      // 监视多个
      watch([count, () => state.msg], (values) => {
        console.log('watch3', values)
      })

      

      function update () {
        
        count.value += 1

        // 更新已有的数据
        // state.msg += '--'
        // state.user.name += '---'
        // 直接给响应式对象添加新属性 ==> vue2不可以, 但vue3中可以
        // state.user.sex = '男'
        // 直接给数组通过下标修改元素 ==> vue2不可以, 但vue3中可以
        // state.numbers[1] = 7
      }

      console.log(toRefs(state)) // 将state对象中的每个属性都包装为ref对象(也就是响应式的)

      return { // 返回对象中的所有属性和方法模板中可以直接使用
        // state,
        // msg: state.msg,  // msg: 'atguigu'
        // user: state.user,
        // numbers: state.numbers,
        // ...state,  // 有问题, 拆解出的每个属性值是非响应式的
        ...toRefs(state), // 可以, 拆解出的每个属性值都是响应式的
        update,
        count
      }
    }
  }
</script>